home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-02
/
pasfoss1.zip
/
AMFOSSIL.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1991-04-18
|
28KB
|
688 lines
{$D-} { Debug Information Off }
{ $S-} { Stack Checking Off }
{$V-} { String Checking Off }
Unit AMFOSSIL;
{ Copyright (C) 1990 Andrew J. Mead
All Rights Reserved.
Contact:
POB 1155 Chapel Hill NC 27514-1155 USA
1:151/223 (Andrew J. Mead) Fido Net
98@9968 WWIV Net
}
{ original version written 4/18/91
AM FOSSIL is FREEWARE. You may distribute it and use it as you will.
Only distribute it in complete form. If you use the routines, please
give credit.
Portions of these routines are used in the BBS Onliner Interface (BOI).
Both Pascal and C source code versions are available from Andrew Mead.
The BBS Onliner Interface allows programmers to easily write online
doors that run under more than 30 different BBS systems, with or
without FOSSIL installed, using standard or non-standard IRQ/port
address combinations, or even using locked bps modems. The BOI is
a SHAREWARE product. Look for BOI???C.ZIP or BOI???P.ZIP where
??? represents the current version number.
}
{ Important Notice :
Most of the documentation provided with each Function and Procedure was
derived (plagerized) from{
Fundamentals of FOSSIL implementation and use
Version 5, February 11, 1988
Rick Moore, Solar Wind Computing
FidoNet Address: 1:115/333
FidoNet Standards Committee index: FSC-0015
Copyright (C) 1988, Rick Moore, Homewood, IL, 60430. All rights reserved.
I urge you to read this document (FSC-0015.DOC) and its companion
(FSC-0015.CHT) before using and FOSSIL routines. This document in either
arc or zip format should be available on any FidoNet BBS near you.
}
INTERFACE
Const
{ These constants only for use with SetContCK, see procedure for more details }
ckenable = $01; { enable ctrl-c/ctrl-k interception }
ckdisable = $00; { disable ctrl-c/ctrl-k interception }
transtop = $02; { halt transmission }
transclr = $00; { resume transmission }
Type
fossinforec = record { for use with Procedure DriverInfo }
info_size : word; { size of the structure in bytes }
curr_fossil : byte; { FOSSIL spec driver conforms to }
curr_rev : byte; { rev level of this specific driver }
id_string : pointer; { "FAR" pointer to ASCIIZ ID string }
ibsize : word; { size of the input buffer (bytes) }
ifree : word; { number of bytes left in buffer }
obsize : word; { size of the output buffer (bytes) }
ofree : word; { number of bytes left in the buffer }
screen_width : byte; { width of screen on this adapter }
screen_height : byte; { height of screen " " }
baudmask : byte { ACTUAL baud rate, computer to modem }
end;
Var
fport : byte; { FOSSIL serial port. 0 = Com1, 1 = Com2, etc. }
fresult : word; { FOSSIL status variable, returned by several Procedures }
fossrev : byte; { FOSSIL revision number }
fossfunc : byte; { highest FOSSIL function supported }
Procedure SETBAUDRATE(mask : byte);{ $00 } { Set modem variables }
Procedure SENDFCHAR(fchar : char); { $01 } { Transmit char with wait }
Procedure READFCHAR(fchar : char); { $02 } { Recieve char with wait }
Procedure GETFSTATUS; { $03 } { Request FOSSIL Status }
Function INITFOSSIL : boolean; { $04 } { Initializes FOSSIL }
Procedure DEINITFOSSIL; { $05 } { Terminates FOSSIL }
Procedure DROPFCARRIER; { $06 } { Disable modem }
Procedure TIMERINFO(var tickint, { $07 } { Get Timer Interrupt Info }
tickpersec : byte;var msecpertick : word);
Procedure FLUSHOUTPUT; { $08 } { Flushes Output Buffer }
Procedure PURGEOUTPUT; { $09 } { Purges Output Buffer }
Procedure PURGEINPUT; { $0A } { Purges Input Buffer }
Procedure SENDFNOW(fchar : char; { $0B } { Send char without wait }
var success : boolean);
Procedure PEAKFCHAR(fchar : char; { $0C } { Non-destructive input read }
var success : boolean);
Procedure READKNOW(var key : word; { $0D } { Read keyboard without wait }
var success : boolean);
Procedure READKBD(var key : word); { $0E } { Read keyboard with wait }
Procedure SETFLOWCONTROL { $0F } { Enable/Disable Flow Control }
(mask : byte);
Procedure SETCONTCK(mask : byte; { $10 } { Control C/K checking }
var ckstate : boolean);
Procedure SETCURSOR(row, { $11 } { Position cursor on screen }
column : byte);
Procedure GETCURSOR(var row, { $12 } { Get cursor location }
column : byte);
Procedure ANSICHAR(fchar : char); { $13 } { Write character to screen }
Procedure SETWATCHDOG { $14 } { enable/disable WatchDog }
(enable : boolean);
Procedure BIOSCHAR(fchar : char); { $15 } { Write character with BIOS }
Procedure SETTICKFUNC { $16 } { Timer Interrupt Handler }
(faddr : pointer;putin : boolean;var success : boolean);
Procedure COLDBOOT; { $17 } { Perform "cold" boot }
Procedure WARMBOOT; { $17 } { Perform "warm" boot }
Procedure READFBLOCK { $18 } { Read block from input buffer }
(buffaddr : pointer; numtoread : word;var numread : word);
Procedure WRITEFBLOCK { $19 } { Write block to output buffer }
(buffaddr : pointer; numtosend : word;var numsent : word);
Procedure SETBREAKSIGNAL { $1A } { Start/Stop break signal }
(startbreak : boolean);
Procedure DRIVERINFO { $1B } { Get FOSSIL information }
(buffaddr : pointer; numtoread : word; var numread : word);
{ These three functions call GetStatus $03 }
Function FCARRIER : boolean; { Carrier Detect }
Function INPUTREADY : boolean; { Input Buffer not empty }
Function OUTPUTREADY : boolean; { Output Buffer not empty }
IMPLEMENTATION
Uses
dos; { for the registers type }
Const
lowerdtr = $00;
Type
ptrmask = record { segment:offset mask for address pointers }
poff : word;
pseg : word
end;
Var
regs : registers;
Procedure SETBAUDRATE(mask : byte);
{ See extended notes after end. of Unit
}
begin {* SetBaudRate *}
regs.ah := $00;
regs.al := mask;
regs.dx := fport;
Intr($14,regs);
fresult := regs.ax { returns FOSSIL status word }
end; {* SetBaudRate *}
Procedure SENDFCHAR(fchar : char);
{ AL contains the character to be sent. If there is room in the transmit
buffer the return will be immediate, otherwise it will wait until there
is room to store the character in the transmit buffer. On return, AX is
set as in a status request.
}
begin {* SendFChar *}
regs.ah := $01;
regs.al := ord(fchar);
regs.dx := fport;
Intr($14,regs);
fresult := regs.ax
end; {* SendFChar *}
Procedure READFCHAR(fchar : char);
{ If there is a character available in the receive buffer, returns with
the next character in AL. It will wait until a character is received if
none is available.
}
begin {* ReadFChar *}
regs.ah := $02;
regs.dx := fport;
Intr($14,regs);
move(regs.al,fchar,1)
end; {* ReadFChar *}
Procedure GETFSTATUS;
{ Returns with the line and modem status in AX. Status bits returned are:
In AH:
Bit 0 = RDA - input data is available in buffer
Bit 1 = OVRN - the input buffer has been overrun. All
characters received after the buffer is
full should be discarded.
Bit 5 = THRE - room is available in output buffer
Bit 6 = TSRE - output buffer is empty
In AL:
Bit 3 = Always 1 (always return with this bit set to 1)
Bit 7 = DCD - carrier detect
This can be used by the application to determine whether carrier detect
(CD) is set, signifying the presence/absence of a remote connection, as
well as monitoring both the input and output buffer status. Bit 3 of AL
is always returned set to enable programs to use it as a carrier detect
bit on hardwired (null modem) links.
}
begin {* GetFStatus *}
regs.ah := $03;
regs.dx := fport;
Intr($14,regs);
fresult := regs.ax
end; {* GetFStatus *}
Function INITFOSSIL : boolean;
{ This is used to tell the driver to begin operations, and to check that
the driver is installed. This function should be called before any other
communications calls are made. DTR is raised by this call. The baud
rate must NOT be changed by this call.
NOTE: Should an additional call to this service occur (2 Inits or Init,
Read,Init, etc.) the driver should reset all buffers, flow control, etc.
to the INIT state and return SUCCESS.
}
begin {* fInitFOSSIL *}
regs.ah := $04;
regs.dx := fport;
Intr($14,regs);
InitFOSSIL := regs.ax = $1954;
fossrev := regs.bh; { FOSSIL version implemented }
fossfunc := regs.bl { highest FOSSIL function supported }
end; {* fInitFOSSIL *}
Procedure DEINITFOSSIL;
{ This is used to tell the driver that comm port operations are ended. The
function should be called when no more comm port functions will be used
on the port specified in DX. DTR is NOT affected by this call.
}
begin {* DeinitFOSSIL *}
regs.ah := $05;
regs.dx := fport;
Intr($14,regs);
end; {* DeinitFOSSIL *}
Procedure DROPFCARRIER;
{ This function is used to control the DTR line to the modem.
AL = 00h means lower DTR (disable the modem), and AL = 01h means to raise
DTR (enable the modem). This procedure only lowers DTR.
}
begin {* DropFCarrier *}
regs.ah := $06;
regs.al := lowerdtr;
regs.dx := fport;
Intr($14,regs);
end; {* DropFCarrier *}
Procedure TIMERINFO(var tickint,tickpersec : byte;var msecpertick : word);
{ This is used to determine the parameters of the timer tick on any given
machine. Applications can use this for critical timing (granularity of
less than one second) or to set up code (such as a watchdog) that is
executed on every timer tick. See function 16h (add/delete function from
timer tick) for the preferred way of actually installing such code.
}
begin {* TimerInfo *}
regs.ah := $07;
Intr($14,regs);
tickint := regs.al; { Timer tick interrupt number }
tickpersec := regs.ah; { Ticks per second on interrupt number }
msecpertick := regs.dx { Approxiamate Milliseconds per Tick }
end; {* TimerInfo *}
Procedure FLUSHOUTPUT;
{ This is used to force any pending output. It does not return until all
pending output has been sent. You should use this call with care. Flow
control (documented below) can make your system hang on this call in a
tight uninterruptible loop under the right circumstances.
}
begin {* FlushOutput *}
regs.ah := $08;
regs.dx := fport;
Intr($14,regs)
end; {* FlushOutput *}
Procedure PURGEOUTPUT;
{ This is used to purge any pending output. Any output data remaining in
the output buffer (not transmitted yet) is discarded.
}
begin {* PurgeOutput *}
regs.ah := $09;
regs.dx := fport;
Intr($14,regs)
end; {* PurgeOutput *}
Procedure PURGEINPUT;
{ This is used to purge any pending input. Any input data which is still
in the buffer is discarded.
}
begin {* PurgeInput *}
regs.ah := $0A;
regs.dx := fport;
Intr($14,regs)
end; {* PurgeInput *}
Procedure SENDFNOW(fchar : char; var success : boolean);
{ This is exactly the same as the "regular" transmit call, except that if
the driver is unable to buffer the character (the buffer is full), a
value of 0000h is returned in AX. If the driver accepts the character
(room is available), 0001h is returned in AX.
}
begin {* SendFNow *}
regs.ah := $0B;
regs.al := ord(fchar);
regs.dx := fport;
Intr($14,regs);
success := regs.ax = $0001
end; {* SendFNow *}
Procedure PEAKFCHAR(fchar : char; var success : boolean);
{ Return in AL the next character in the receive buffer. If the receive
buffer is empty, return FFFFh. The character returned remains in
the receive buffer.
}
begin {* PeakFChar *}
regs.ah := $0C;
regs.dx := fport;
Intr($14,regs);
if regs.ah = $00 then
begin
move(regs.al,fchar,1);
success := true
end
else { regs.ax should equal $FFFF }
begin
fchar := char(00);
success := false
end
end; {* PeakFChar *}
Procedure READKNOW(var key : word; var success : boolean);
{ Return in AX the next character (non-destructive read ahead) from the
keyboard; if nothing is currently in the keyboard buffer, return FFFFh in
AX. Use IBM-style function key mapping in the high order byte. Scan
codes for non-"function" keys are not specifically required, but may be
included. Function keys return 00h in AL and the "scan code" in AH.
}
begin {* ReadKNow *}
regs.ah := $0D;
Intr($14,regs);
success := regs.ax <> $FFFF;
if success then key := regs.ax else key := $0000
end; {* ReadKNow *}
Procedure READKBD(var key : word);
{ Return in AX the next character from the keyboard; wait if no character
is available. Keyboard mapping should be the same as function 0Dh.
}
begin {* ReadKBD *}
regs.ah := $0E;
Intr($14,regs);
key := regs.ax
end; {* ReadKBD *}
Procedure SETFLOWCONTROL(mask : byte);
{ Enable or Disable Flow Control. See Extended notes after end. of Unit
}
begin {* SetFlowControl *}
regs.ah := $0F;
regs.al := mask;
regs.dx := fport;
Intr($14,regs)
end; {* SetFlowControl *}
Procedure SETCONTCK(mask : byte; var ckstate : boolean);
{ mask should be called as a combination of either (ckenable,ckdisable) OR
(transtop,transclr). i.e. SetContCK(ckenable or transclr,retstate);
This is used for BBS operation, primarily. A bit mask is passed in AL
with the following flags:
Bit 0 Enable/disable Control-C / Control-K checking
Bit 1 Disable/enable the transmitter
The Enable (bit 0 = 1) and Disable (Bit 0 = 0) Control-C/Control-K check
function is meant primarily for BBS use. When the checking is enabled, a
Control-C or Control-K received from the communications port will set a
flag internal to the FOSSIL driver, but will not be stored in the input
buffer. The next use of this function will return the value of this flag
in register AX then clear the flag for the next occurrence. The returned
value is used by the BBS software to determine whether output should be
halted or not.
The Disable (Bit 1 = 1) and Enable (Bit 1 = 0) Transmitter function lets
the application restrain the asynchronous driver from output in much the
same way as XON/XOFF would.
}
begin {* SetContCK *}
regs.ah := $10;
regs.al := mask;
regs.dx := fport;
Intr($14,regs);
ckstate := regs.ax = $0001 { Ctrl-C/Ctrl-K has been recieved }
end; {* SetContCK *}
Procedure SETCURSOR(row,column : byte);
{ This function looks exactly like INT 10h, subfuction 2, on the IBM PC.
The cursor location is passed in DX: row in DH and column in DL. The
function treats the screen as a coordinate system whose origin (0,0) is
the upper left hand corner of the screen.
}
begin {* SetCursor *}
regs.ah := $11;
regs.dh := row;
regs.dl := column;
Intr($14,regs)
end; {* SetCursor *}
Procedure GETCURSOR(var row,column : byte);
{ Looks exactly like INT 10h, subfunction 3, on the IBM PC. The current
cursor location (using the same coordinate system as function 16h) is
passed back in DX.
}
begin {* GetCursor *}
regs.ah := $12;
Intr($14,regs);
row := regs.dh;
column := regs.dl
end; {* GetCursor *}
Procedure ANSICHAR(fchar : char);
{ The character in AL is sent to the screen by the fastest method possible
that allows ANSI processing to occur (if available). This routine should
not be used in such a way that DOS output (which is not re-entrant) can
not be employed by some FOSSIL driver to perform the function (in fact,
on the IBM PC that is likely to be how it's done).
}
begin
regs.ah := $13;
regs.al := ord(fchar);
Intr($14,regs)
end;
Procedure SETWATCHDOG(enable : boolean);
{ When watchdog is enabled, the state of the carrier detect (CD) line on
the comm port specified in DX should be constantly monitored. Should the
state of that line become FALSE (carrier lost), the system should be re-
booted, to enable the BBS (or other application) to start up again. This
monitor is not affected by Init/Uninit etc.
}
begin {* SetWatchDog *}
regs.ah := $14;
if enable then regs.al := $01 else regs.al := $00;
regs.dx := fport;
Intr($14,regs)
end; {* SetWatchDog *}
Procedure BIOSCHAR(fchar : char);
{ The character in AL is sent to the screen using BIOS-level Input/Output
routines. This differs from function 13h in that DOS I/O CAN NOT be used,
as this function might be called from driver level.
}
begin {* BIOSChar *}
regs.ah := $15;
regs.al := ord(fchar);
Intr($14,regs)
end; {* BIOSChar *}
Procedure SETTICKFUNC(faddr : pointer;putin : boolean;var success : boolean);
{ This function is used to allow a central authority to manage the timer
interrupts, so that as code is loaded and unloaded, the integrity of the
"chain" is not compromised. Rather than using the traditional method of
saving the old contents of the timer vector, storing the address of your
routine there, and executing a far call to the "old" routine when yours
is done, instead you call this function. It manages a list of such entry
points and calls them on a timer tick (interrupt) using a FAR call. All
the usual cautions about making DOS calls apply (that is, DON'T!).
This makes it possible for a program to get in and out of the tick chain
without having to know whether another program has also done so since it
first insinuated itself. At least 4 entries should be available in the
driver's table (including one to be used by Watchdog if implemented that
way).
}
var
tickfunc : ptrmask absolute faddr;
begin {* SetTickFunc *}
regs.ah := $16;
if putin then regs.al := $01 else regs.al := $00;
regs.es := tickfunc.pseg; { Segment of function }
regs.dx := tickfunc.poff; { Offset of function }
Intr($14,regs);
success := regs.ax = $0000
end; {* SetTickFunc *}
Procedure COLDBOOT;
{ Used in extreme emergency by code that can't seem to find a "clean" way
out of the trouble it has gotten itself into. Hopefully it won't happen
while you're computing something in the other half of a DoubleDOS system.
A "cold" boot is contains a power-up, self-test and boot, a "warm" boot
just re-boots the computer.
}
begin {* ColdBoot *}
regs.ah := $17;
regs.al := $00;
Intr($14,regs)
end; {* ColdBoot *}
Procedure WARMBOOT;
{ See definition in Procedure ColdBoot
}
begin {* WarmBoot *}
regs.ah := $17;
regs.al := $01;
Intr($14,regs)
end; {* WarmBoot *}
Procedure READFBLOCK(buffaddr : pointer;numtoread : word;var numread : word);
{ A "no-wait" block read of 0 to FFFFh characters from the FOSSIL inbound
ring buffer to the calling routine's buffer. ES:DI are left unchanged by
the call; the count of bytes actually transferred will be returned in AX.
}
var
buffer : ptrmask absolute buffaddr;
begin {* ReadFBlock *}
regs.ah := $18;
regs.cx := numtoread;
regs.dx := fport;
regs.es := buffer.pseg;
regs.di := buffer.poff;
Intr($14,regs);
numread := regs.ax
end; {* ReadFBlock *}
Procedure WRITEFBLOCK(buffaddr : pointer;numtosend : word;var numsent : word);
{ A "no-wait" block move of 0 to FFFFh characters from the calling
program's buffer into the FOSSIL outbound ring buffer. ES:DI are left
unchanged by the call; the count of bytes actually transferred will be
returned in AX.
}
var
buffer : ptrmask absolute buffaddr;
begin {* WriteFBlock *}
regs.ah := $19;
regs.cx := numtosend;
regs.dx := fport;
regs.es := buffer.pseg;
regs.di := buffer.poff;
Intr($14,regs);
numsent := regs.ax
end; {* WriteFBlock *}
Procedure SETBREAKSIGNAL(startbreak : boolean);
{ Send a break signal to the modem. If AL=01h the driver will commence the
transmission of a break. If AL=00h the driver will end the break. This
is useful for communications with devices that can only go into 'command
mode' when a BREAK is received. Note: the application is responsible for
the timing of the BREAK. Also, if the FOSSIL has been restrained by an
Xoff received from the modem, the flag will be cleared. An Init or Un-
Init will stop an in-progress BREAK.
}
begin {* SetBreakSignal *}
regs.ah := $1A;
if startbreak then regs.al := $01 else regs.al := $00;
regs.dx := fport;
Intr($14,regs)
end; {* SetBreakSignal *}
Procedure DRIVERINFO(buffaddr : pointer; numtoread : word;var numread : word);
{ Transfer information about the driver and its current status to the user
for use in determining, at the application level, limits of the driver.
Designed to assist "generic" applications to adjust to "foreign" gear.
the Type fossinforec has been added (but untested) for your convenience.
The ident string should be null-terminated, and NOT contain a newline.
The baud rate byte contains the bits that Function 00h would use to set
the port to that speed.
The fields related to a particular port (buffer size, space left in the
buffer, baud rate) will be undefined if port FFh or an invalid port is
contained in DX.
Additional information will always be passed after these, so that, for
example, offset "sheight" will never change with FOSSIL revision changes.
}
var
infobuff : ptrmask absolute buffaddr;
begin {* DriverInfo *}
regs.ah := $1B;
regs.cx := numtoread;
regs.dx := fport;
regs.es := infobuff.pseg;
regs.di := infobuff.poff;
Intr($14,regs);
numread := regs.ax
end; {* DriverInfo *}
Function FCARRIER : boolean;
{ AL Bit 7 = DCD - carrier detect }
begin {*f FCarrier *}
GetFStatus;
FCarrier := lo(fresult) and $80 = $80
end; {* fFCarrier *}
Function INPUTREADY : boolean;
{ AH Bit 0 = RDA - input data is available in buffer }
begin { fInputReady *}
GetFStatus;
InputReady := hi(fresult) and $01 = $01
end; {* fInputReady *}
Function OUTPUTREADY : boolean;
{ AH Bit 5 = THRE - room is available in output buffer }
begin {* fOutputReady *}
GetFStatus;
OutputReady := hi(fresult) and $20 = $20
end; {* fOutputReady *}
end. Unit
The following is more in depth documentation regarding the following
procedures. They are not used by the BBS Onliner Interface, and are
included only for completeness. To implement these procedures in other
programs, you will probably want to implement certain predeclared constants
to allow for easier coding of the 'mask' variables.
Procedure SETBAUDRATE(mask : byte);
Procedure SETFLOWCONTROL(mask : byte);
SetBaudRate
AH = 00h Set baud rate
Parameters:
Entry: AL = Baud rate code
DX = Port number
Exit: AX = Port status (see function 03h)
This works the same as the equivalent IBM PC BIOS call, except that it
ONLY selects a baud rate. This is passed in the high order 3 bits of AL
as follows:
010 = 300 baud
011 = 600 ''
100 = 1200 ''
101 = 2400 ''
110 = 4800 ''
111 = 9600 ''
000 = 19200 '' (Replaces old 110 baud mask)
001 = 38400 '' (Replaces old 150 baud mask)
The low order 5 bits can be implemented or not by the FOSSIL, but in all
cases, if the low order bits of AL are 00011, the result should be that
the communications device should be set to eight data bits, one stop bit
and no parity. This setting is a MINIMUM REQUIREMENT of Fido, Opus and
SEAdog. For purposes of completeness, here are the IBM PC "compatible"
bit settings:
Bits 4-3 define parity: 0 0 no parity
1 0 no parity
0 1 odd parity
1 1 even parity
Bit 2 defines stop bits: 0 1 stop bit;
1 1.5 bits for 5-bit char;
2 for others
Bits 1-0 character length: 0 0 5 bits
0 1 6 bits
1 0 7 bits
1 1 8 bits
SetFlowControl
AH = 0Fh Enable or disable flow control
Parameters:
Entry: AL = Bit mask describing requested flow control
DX = Port number
Exit: None
TRANSMIT flow control allows the "other end" to restrain the transmitter
when you are over-running it. RECEIVE flow control tells the FOSSIL to
attempt to do just that if it is being overwhelmed.
Two kinds of basic flow control are supported:
Bit 0 = 1 Xon/Xoff on transmit
Bit 1 = 1 CTS/RTS (CTS on transmit, RTS on receive)
Bit 2 Reserved
Bit 3 = 1 Xon/Xoff on Receive
Flow control is enabled, or disabled, by setting the appropriate bits in
AL for the types of flow control we want to ENABLE (value = 1), and/or
DISABLE (value = 0), and calling this function. Bit 2 is reserved for
DSR/DTR, but is not currently supported in any implementation.
Enabling transmit Xon/Xoff will cause the FOSSIL to stop transmitting
upon receiving an Xoff. The FOSSIL will resume transmitting when an Xon
is received.
Enabling CTS/RTS will cause the FOSSIL to cease transmitting when CTS is
lowered. Transmission will resume when CTS is raised. The FOSSIL will
drop RTS when the receive buffer reaches a predetermined percentage full
The FOSSIL will raise RTS when the receive buffer empties below the
predetermined percentage full. The point(s) at which this occurs is
left to the individual FOSSIL implementor.
Enabling receive Xon/Xoff will cause the FOSSIL to send a Xoff when the
receive buffer reaches a pre-determined percentage full. An Xon will be
sent when the receive buffer empties below the pre-determined percentage
full. The point(s) at which this occurs is left to the individual FOSSIL
implementor.
Applications using this function should set all bits ON in the high
nibble of AL as well. There is a compatible (but not identical) FOSSIL
driver implementation that uses the high nibble as a control mask. If
your application sets the high nibble to all ones, it will always work,
regardless of the method used by any given driver.